home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-09-27 | 6.2 KB | 213 lines | [TEXT/YHS2] |
- module PreludeArray ( Array, array, listArray, (!), bounds,
- indices, elems, assocs, accumArray, (//), accum, amap,
- ixmap
- ) where
-
- {-#Prelude#-} -- Indicates definitions of compiler prelude symbols
-
- -- This module uses some simple techniques with updatable vectors to
- -- avoid vector copying in loops where single threading is obvious.
- -- This is rather fragile and depends on the way the compiler handles
- -- strictness.
-
- import PreludeBltinArray
- import PreludeArrayInternal
-
- infixl 9 !
- infixl 9 //
-
- data (Ix a) => Array a b = MkArray (a,a) {-#STRICT#-}
- (Vector (Box b)) {-#STRICT#-}
- deriving ()
-
- array :: (Ix a) => (a,a) -> [(a,b)] -> Array a b
- listArray :: (Ix a) => (a,a) -> [b] -> Array a b
- (!) :: (Ix a) => Array a b -> a -> b
- bounds :: (Ix a) => Array a b -> (a,a)
- indices :: (Ix a) => Array a b -> [a]
- elems :: (Ix a) => Array a b -> [b]
- assocs :: (Ix a) => Array a b -> [(a,b)]
- accumArray :: (Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)]
- -> Array a b
- (//) :: (Ix a) => Array a b -> [(a,b)] -> Array a b
- accum :: (Ix a) => (b -> c -> b) -> Array a b -> [(a,c)]
- -> Array a b
- amap :: (Ix a) => (b -> c) -> Array a b -> Array a c
- ixmap :: (Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c
- -> Array a c
-
- -- Arrays are a datatype containing a bounds pair and a vector of values.
- -- Uninitialized array elements contain an error value.
-
- -- Primitive vectors now contain only unboxed values. This permits us to
- -- treat array indexing as an atomic operation without forcing the element
- -- being accessed. The boxing and unboxing of array elements happens
- -- explicitly using these operations:
-
- data Box a = MkBox a
- unBox (MkBox x) = x
- {-# unBox :: Inline #-}
-
-
- -- Array construction and update using index/value associations share
- -- the same helper function.
-
- array b@(bmin, bmax) ivs =
- let size = (index b bmax) + 1
- v = primMakeVector size uninitializedArrayError
- in (MkArray b (updateArrayIvs b v ivs))
- {-# array :: Inline #-}
-
- a@(MkArray b v) // ivs =
- let v' = primCopyVector v
- in (MkArray b (updateArrayIvs b v' ivs))
- {-# (//) :: Inline #-}
-
- updateArrayIvs b v ivs =
- let g (i,x) next = strict1 (primVectorUpdate v (index b i) (MkBox x))
- next
- in foldr g v ivs
- {-# updateArrayIvs :: Inline #-}
-
- uninitializedArrayError =
- MkBox (error "(!){PreludeArray}: uninitialized array element.")
-
-
- -- when mapping a list onto an array, be smart and don't do full index
- -- computation
-
- listArray b@(bmin, bmax) vs =
- let size = (index b bmax) + 1
- v = primMakeVector size uninitializedArrayError
- in (MkArray b (updateArrayVs size v vs))
- {-# listArray :: Inline #-}
-
- updateArrayVs size v vs =
- let g x next j = if (j == size)
- then v
- else strict1 (primVectorUpdate v j (MkBox x))
- (next (j + 1))
- in foldr g (\ _ -> v) vs 0
- {-# updateArrayVs :: Inline #-}
-
-
- -- Array access
-
- a@(MkArray b v) ! i = unBox (primVectorSel v (index b i))
- {-# (!) :: Inline #-}
-
- bounds (MkArray b _) = b
-
- indices = range . bounds
-
-
- -- Again, when mapping array elements into a list, be smart and don't do
- -- the full index computation for every element.
-
- elems a@(MkArray b@(bmin, bmax) v) =
- build (\ c n ->
- let size = (index b bmax) + 1
- g j = if (j == size)
- then n
- else c (unBox (primVectorSel v j)) (g (j + 1))
- -- This strict1 is so size doesn't get inlined and recomputed
- -- at every iteration. It should also force the array argument
- -- to be strict.
- in strict1 size (g 0))
- {-# elems :: Inline #-}
-
- assocs a@(MkArray b@(bmin, bmax) v) =
- build (\ c n ->
- let g i next j = let y = unBox (primVectorSel v j)
- in c (i,y) (next (j + 1))
- in foldr g (\ _ -> n) (range b) 0)
- {-# assocs :: Inline #-}
-
-
- -- accum and accumArray share the same helper function. The difference is
- -- that accum makes a copy of an existing array and accumArray creates
- -- a new one with all elements initialized to the given value.
-
- accum f a@(MkArray b v) ivs =
- let v' = primCopyVector v
- in (MkArray b (accumArrayIvs f b v' ivs))
- {-# accum :: Inline #-}
-
- accumArray f z b@(bmin, bmax) ivs =
- let size = (index b bmax) + 1
- v = primMakeVector size (MkBox z)
- in (MkArray b (accumArrayIvs f b v ivs))
- {-# accumArray :: Inline #-}
-
-
- -- This is a bit tricky. We need to force the access to the array element
- -- before the update, but not force the thunk that is the value of the
- -- array element unless f is strict.
-
- accumArrayIvs f b v ivs =
- let g (i,x) next =
- let j = index b i
- y = primVectorSel v j
- in strict1
- y
- (strict1 (primVectorUpdate v j (MkBox (f (unBox y) x)))
- next)
- in foldr g v ivs
- {-# accumArrayIvs :: Inline #-}
-
-
- -- again, be smart and bypass full array indexing on array mapping
-
- amap f a@(MkArray b@(bmin, bmax) v) =
- let size = (index b bmax) + 1
- v' = primMakeVector size uninitializedArrayError
- g j = if (j == size)
- then v'
- else let y = primVectorSel v j
- in strict1 (primVectorUpdate v' j (MkBox (f (unBox y))))
- (g (j + 1))
- in (MkArray b (g 0))
- {-# amap :: Inline #-}
-
-
- -- can't bypass the index computation here since f needs it as an argument
-
- ixmap b f a = array b [(i,a ! f i) | i <- range b]
- {-# ixmap :: Inline #-}
-
-
- -- random other stuff
-
- instance (Ix a, Eq b) => Eq (Array a b) where
- a == a' = assocs a == assocs a'
-
- instance (Ix a, Ord b) => Ord (Array a b) where
- a <= a' = assocs a <= assocs a'
-
- instance (Ix a, Text a, Text b) => Text (Array a b) where
- showsPrec p a = showParen (p > 9) (
- showString "array " .
- shows (bounds a) . showChar ' ' .
- shows (assocs a) )
-
- readsPrec p = readParen (p > 9)
- (\r -> [(array b as, u) | ("array",s) <- lex r,
- (b,t) <- reads s,
- (as,u) <- reads t ]
- ++
- [(listArray b xs, u) | ("listArray",s) <- lex r,
- (b,t) <- reads s,
- (xs,u) <- reads t ])
-
-
-
- module PreludeArrayInternal where
-
- {-# Prelude #-}
-
- -- These are internal data types
-
- data Vector a = MkVector a
- data Delay a = MkDelay a
-
-